package com.donger.mes.system.side.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.donger.mes.system.side.dto.MaterialReportVO;
import com.donger.mes.system.side.dto.MesSideWarehouseOrderDTO;
import com.donger.mes.system.side.dto.MesSideWarehouseOrderItemDTO;
import com.donger.mes.system.side.entity.MesSideWarehouse;
import com.donger.mes.system.side.entity.MesSideWarehouseLog;
import com.donger.mes.system.side.entity.MesSideWarehouseOrder;
import com.donger.mes.system.side.enums.SideTypeEnums;
import com.donger.mes.system.side.mapper.MesSideWarehouseLogMapper;
import com.donger.mes.system.side.mapper.MesSideWarehouseMapper;
import com.donger.mes.system.side.service.MesSideWarehouseOrderService;
import com.donger.mes.system.side.service.MesSideWarehouseService;
import com.donger.common.core.utils.BizException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class MesSideWarehouseServiceImpl implements MesSideWarehouseService {

    private final MesSideWarehouseMapper mesSideWarehouseMapper;

    private final MesSideWarehouseOrderService mesSideWarehouseOrderService;

    private final MesSideWarehouseLogMapper mesSideWarehouseLogMapper;


    @Override
    public IPage<MesSideWarehouse> page(IPage<MesSideWarehouse> page, Wrapper<MesSideWarehouse> query) {
        return mesSideWarehouseMapper.selectPage(page,query);
    }

    @Override
    public MesSideWarehouse output(String barcode, Float num, String type,String siteCode) {
        return this.output(barcode,num,type,siteCode,"");
    }

    @Override
    @Transactional
    public MesSideWarehouse output(String barcode, Float num, String type,String siteCode,String orderCode) {
        //
        MesSideWarehouse mesSideWarehouse = Optional.ofNullable(mesSideWarehouseMapper.selectOne(Wrappers.<MesSideWarehouse>lambdaQuery()
                        .eq(MesSideWarehouse::getMatBarcode, barcode)
                        .eq(!StrUtil.isEmpty(siteCode),MesSideWarehouse::getSiteCode,siteCode)
                )
        ).orElseThrow(() -> new BizException("线边库不存在该物料"));

        if(mesSideWarehouse.getCurrentNumber() < num){
            throw new BizException("仓库物料数量不足不能出库");
        }

        mesSideWarehouse.setCurrentNumber(mesSideWarehouse.getCurrentNumber() - num);

        if(mesSideWarehouse.getCurrentNumber() == 0){
            // 如果全部投料  则删除数据
            mesSideWarehouseMapper.deleteById(mesSideWarehouse.getId());

        }else{
            mesSideWarehouseMapper.updateById(mesSideWarehouse);
        }
        MesSideWarehouseLog log = new MesSideWarehouseLog();
        BeanUtil.copyProperties(mesSideWarehouse,log);
        log.setId(null);
        log.setType(SideTypeEnums.OUTPUT.getType());
        log.setNum(num);
        log.setOrderCode(orderCode);
        log.setSiteCode(siteCode);
        mesSideWarehouseLogMapper.insert(log);



        return mesSideWarehouse;
    }

    @Override
    @Transactional
    public List<MesSideWarehouse> output(String orderCode) {
        MesSideWarehouseOrderDTO mesSideWarehouseOrderDTO = mesSideWarehouseOrderService.getOrderByCode(orderCode);
        List<MesSideWarehouseOrderItemDTO> items = mesSideWarehouseOrderDTO.getItems();
        for (MesSideWarehouseOrderItemDTO item: items){
            output(item.getMatBarcode(),item.getNum(),"",orderCode);
        }
        return null;
    }

    @Override
    public void input(MesSideWarehouse mesSideWarehouse) {

        this.input(mesSideWarehouse,"");
    }

    @Override
    @Transactional
    public void input(MesSideWarehouse mesSideWarehouse,String orderCode) {

        MesSideWarehouse tmp = mesSideWarehouseMapper.selectOne(Wrappers.<MesSideWarehouse>lambdaQuery()
                .eq(MesSideWarehouse::getMatBarcode, mesSideWarehouse.getMatBarcode()));

        // 新增这个
        if(tmp == null){
            mesSideWarehouseMapper.insert(mesSideWarehouse);
        }else{
            tmp.setCurrentNumber(tmp.getCurrentNumber() + mesSideWarehouse.getCurrentNumber());
            mesSideWarehouseMapper.updateById(tmp);
        }

        // 生成对应的入库日志
        MesSideWarehouseLog log = new MesSideWarehouseLog();
        BeanUtil.copyProperties(mesSideWarehouse,log);
        log.setType(SideTypeEnums.INPUT.getType());
        log.setOrderCode(orderCode);
        log.setNum(mesSideWarehouse.getCurrentNumber());
        mesSideWarehouseLogMapper.insert(log);
    }

    @Override
    @Transactional
    public void input(String orderCode) {

        MesSideWarehouseOrderDTO mesSideWarehouseOrderDTO = mesSideWarehouseOrderService.getOrderByCode(orderCode);

        // 获取对应的数据进行入库

        List<MesSideWarehouseOrderItemDTO> items = mesSideWarehouseOrderDTO.getItems();
        for (MesSideWarehouseOrderItemDTO item: items){
            MesSideWarehouse mesSideWarehouse = new MesSideWarehouse();
            BeanUtil.copyProperties(item,mesSideWarehouse);
            mesSideWarehouse.setCurrentNumber(item.getNum());
            input(mesSideWarehouse,orderCode);
        }

    }

    @Override
    public List<MaterialReportVO> reportMatNum(List<String> matCodes) {
        if(CollUtil.isEmpty(matCodes)){
            throw new BizException("物料编码集合不能为空");
        }
        List<Map<String, Object>> maps = mesSideWarehouseMapper.selectMaps(Wrappers.<MesSideWarehouse>query()
                .select("sum(current_number) num,mat_code,mat_name").in("mat_code",matCodes)
                .groupBy("mat_code","mat_name")
        );
        log.info("数据 -》 {}", JSONUtil.parse(maps).toString());
        List<MaterialReportVO> collect = maps.stream().map(item -> {
            MaterialReportVO materialReportVO = new MaterialReportVO();
            materialReportVO.setMatCode(item.get("mat_code").toString());
            materialReportVO.setMatName(item.get("mat_name").toString());
            materialReportVO.setNum(Float.valueOf(item.get("num").toString()));
            return materialReportVO;
        }).collect(Collectors.toList());

        return collect;
    }
}
